home *** CD-ROM | disk | FTP | other *** search
- char *numeric_revision = "tiprz 1.00";
- /*+-------------------------------------------------------------------------
- tiprz.c - X/Y/ZMODEM receive program
- Derived from public domain source by Chuck Forsberg, Omen Technologies
- wht%n4hgf@emory.mathcs.emory.edu
-
- Defined functions:
- SIGALRM_handler()
- arg_token(parsestr,termchars)
- bye_bye(sig)
- cancel_transaction(sig)
- close_and_report()
- flushline()
- fname_split(cmd,arg,arg_max_quan,narg_rtn)
- fname_too_long(fname)
- fname_truncated()
- getfree()
- isanylc(str)
- main(argc,argv,envp)
- make_dirs(pathname)
- mkdir(dpath,dmode)
- procheader(name)
- purgeline()
- readline(timeout)
- rzfile()
- rzfiles()
- send_ZFIN_and_exit()
- send_cancel()
- sendline(c)
- substr(str,token)
- sys2(shellcmd)
- tryz()
- uncaps(str)
- usage(fail_reason)
- wcgetsec(rxbuf,maxtime)
- wcreceive(argc,argp)
- wcrx()
- wcrxpn(rpn)
- write_sec_to_disk(buf,n)
- xsendline(c)
-
- Usage: tiprz -Z [-abeuy] (ZMODEM)
- tiprz -Y [-abuy] (YMODEM)
- tiprz -X [-abc] file (XMODEM or XMODEM-1k)
-
- -a ASCII transfer (strip CR)
- -b Binary transfer for all files
- -c Use 16 bit CRC (XMODEM)
- -e Escape control characters (ZMODEM)
- -p protect local files (ZMODEM)
- -t <tenths> rx timeout seconds
- -+ force append
- -u convert uppercase filenames to lower case
- -y Yes, clobber existing file if any
- -. line fd to use
- -, log protocol packets
-
- --------------------------------------------------------------------------*/
- /*+:EDITS:*/
- /*:05-21-1990-16:00-wht@tridom-adapt ecu xfer protocols for tipwht */
-
- #include <stdio.h>
- #include <signal.h>
- #include <setjmp.h>
- #include <ctype.h>
- #include <errno.h>
- #include <fcntl.h>
- #include "zmodem.h"
- #include "zlint.h"
-
- char *strrchr();
-
- #if defined(M_UNIX)
- char *fname_truncated();
- #endif
-
- extern unsigned short crctab[];
- extern unsigned long total_data_chars_xfered; /* zcurses.c */
- extern int errno;
- extern char *sys_errlist[];
- extern char Attn[]; /* Attention string rx sends to tx on err */
- extern int Crc32; /* Display flag indicating 32 bit CRC being received */
- extern int Rxcount; /* Count of data bytes received */
- extern char Rxhdr[]; /* Received header */
- extern char Txhdr[]; /* Transmitted header */
- extern int Rxtimeout; /* Tenths of seconds to wait for something */
- extern char s256[];
-
- /* Max value for VMIN_COUNT is 255. A larger value reduces system
- overhead but may evoke kernel bugs. 133 corresponds to an XMODEM/CRC
- sector */
- #if !defined(VMIN_COUNT)
- #define VMIN_COUNT 133
- #endif
- unsigned char vmin_count = VMIN_COUNT;
- int Readnum = VMIN_COUNT; /* num bytes to ask for in read() from modem */
-
- #define DEFBYTL 2000000000L /* default rx file size */
- #define RETRYMAX 5
-
- FILE *fout;
- char Lzmanag; /* Local file management request */
- char Pathname[PATHLEN];
- char curr_dir[256];
- unsigned char linbuf[VMIN_COUNT];
- char s128[128];
- char secbuf[1025];
- char zconv; /* ZMODEM file conversion request */
- char zmanag; /* ZMODEM file management request */
- char ztrans; /* ZMODEM file transport request */
- int Batch=0;
- int Blklen; /* record length of received packets */
- int Crcflg;
- int Eofseen; /* indicates cpm eof (^Z) has been received */
- int Filcnt=0; /* count of number of files opened */
- int Filemode; /* Unix style mode for incoming file */
- int Firstsec;
- int Lastrx;
- int Lleft=0; /* number of characters in linbuf */
- int MakeLCPathname=1; /* make received pathname lower case */
- int Nozmodem = 0; /* If invoked as "rb" */
- int Rxascii=0; /* receive files in ascii (translate) mode */
- int Rxbinary=0; /* receive all files in bin mode */
- int Rxclob=0; /* Clobber existing file */
- int Thisbinary; /* current file is to be received in bin mode */
- int Twostop = 0; /* use two stop bits */
- int Zctlesc; /* Encode control characters */
- int Zmodem=0; /* ZMODEM protocol requested */
- int Zrwindow = 1400; /* RX window size (controls garbage count) */
- int tipsz_flag = 0;
- int skip_count = 0; /* skipped files */
- int errors;
- int iofd = 0;
- int log_packets = 0;
- int npats = 0;
- int oldBlklen = -1; /* last block length */
- int this_file_errors = 0;
- int tryzhdrtype=ZRINIT; /* Header type to send corresponding to Last rx close */
- jmp_buf tohere; /* For the interrupt on RX timeout */
- long Bytesleft; /* number of bytes of incoming file left */
- long Modtime; /* Unix style mod time for incoming file */
- long TotalToReceive = 0L;
- long rx_char_count = 0L;
- long tx_char_count = 0L;
- struct stat fout_stat;
- time_t timep[2];
- unsigned Baudrate;
- unsigned long this_file_length;
- int required_type = 0;
- char *bottom_label = (char *)0;
-
- /*+-----------------------------------------------------------------------
- arg_token(parsestr,termchars)
-
- Get next token from string parsestr ((char *)0 on 2nd, 3rd, etc.
- calls), where tokens are nonempty strings separated by runs of chars
- from termchars. Writes nulls into parsestr to end tokens.
- termchars need not remain constant from call to call.
-
- Treats multiple occurrences of a termchar as one delimiter (does not
- allow null fields).
- ------------------------------------------------------------------------*/
- #if defined(M_UNIX)
- static char *arg_token_static = (char *)0;
- char *arg_token(parsestr,termchars)
- char *parsestr;
- char *termchars;
- {
- register int first = 1;
- register char *termptr;
- register char *parseptr;
- char *token;
-
- if(parsestr == (char *)0 && arg_token_static == (char *)0)
- return((char *)0);
-
- if(parsestr)
- parseptr = parsestr;
- else
- parseptr = arg_token_static;
-
- while(*parseptr)
- {
- if(!strchr(termchars,*parseptr))
- break;
- parseptr++;
- }
-
- if(!*parseptr)
- {
- arg_token_static = (char *)0;
- return((char *)0);
- }
-
- token = parseptr;
- if(*token == '\'')
- {
- token++;
- parseptr++;
- while(*parseptr)
- {
- if(*parseptr == '\'')
- {
- arg_token_static = parseptr + 1;
- *parseptr = 0;
- return(token);
- }
- parseptr++;
- }
- arg_token_static = (char *)0;
- return(token);
- }
- while(*parseptr)
- {
- if(strchr(termchars,*parseptr))
- {
- *parseptr = 0;
- arg_token_static = parseptr + 1;
- while(*arg_token_static)
- {
- if(!strchr(termchars,*arg_token_static))
- break;
- arg_token_static++;
- }
- return(token);
- }
- parseptr++;
- }
- arg_token_static = (char *)0;
- return(token);
- } /* end of arg_token */
- #endif
-
- /*+-------------------------------------------------------------------------
- fname_split(cmd,arg,arg_max_quan,&narg)
- --------------------------------------------------------------------------*/
- #if defined(M_UNIX)
- void
- fname_split(cmd,arg,arg_max_quan,narg_rtn)
- char *cmd;
- char **arg;
- int arg_max_quan;
- int *narg_rtn;
- {
- register itmp;
- register narg;
-
- for(itmp = 0; itmp < arg_max_quan; itmp++)
- arg[itmp] = (char *)0;
- arg[0] = arg_token(cmd,"/");
-
- for(narg = 1; narg < arg_max_quan; ++narg)
- {
- if((arg[narg] = arg_token((char *)0,"/")) == (char *)0)
- break;
- }
-
- *narg_rtn = narg;
-
- } /* end of fname_split */
- #endif
-
- #if defined(M_UNIX)
- #define MAX_COMPONENT_LEN 14
- #define MAX_PATH_COMPONENTS 16
- static char trunc_fname[257];
- static char *trunc_components[MAX_PATH_COMPONENTS];
- static int trunc_components_quan;
- static int trunc_absolute_path;
- #endif
-
- /*+-------------------------------------------------------------------------
- fname_too_long(fname) - check for any pathname component too long
- --------------------------------------------------------------------------*/
- #if defined(M_UNIX)
- int
- fname_too_long(fname)
- register char *fname;
- {
- register int itmp;
- register char **cpptr;
-
- if(trunc_absolute_path = (*fname == '/'))
- fname++;
- strncpy(trunc_fname,fname,sizeof(trunc_fname) - 1);
- fname_split(trunc_fname,trunc_components,
- MAX_PATH_COMPONENTS,&trunc_components_quan);
- itmp = trunc_components_quan;
- cpptr = trunc_components;
- while(itmp--)
- {
- if(strlen(*cpptr) > MAX_COMPONENT_LEN)
- return(1);
- cpptr++;
- }
- return(0);
- } /* end of fname_too_long */
- #endif
-
- /*+-------------------------------------------------------------------------
- fname_truncated() - build truncated path last checked by fname_too_long
- --------------------------------------------------------------------------*/
- #if defined(M_UNIX)
- char *
- fname_truncated()
- {
- register int icomp;
- char new_fname[257];
- register char *cptr = new_fname;
-
- if(trunc_absolute_path)
- {
- *cptr = '/';
- *(cptr + 1) = 0;
- }
- else
- *cptr = 0;
- for(icomp = 0; icomp < trunc_components_quan; icomp++)
- {
- if(strlen(trunc_components[icomp]) > MAX_COMPONENT_LEN)
- *(trunc_components[icomp] + MAX_COMPONENT_LEN) = 0;
- strcat(cptr,trunc_components[icomp]);
- if(icomp < trunc_components_quan - 1)
- strcat(cptr,"/");
- }
- strcpy(trunc_fname,cptr);
- return(trunc_fname);
-
- } /* end of fname_truncated */
- #endif
-
- /*+-------------------------------------------------------------------------
- substr(str,token)
-
- searches for token in string str returns pointer to token within
- string if found,NULL otherwise
- --------------------------------------------------------------------------*/
- char *
- substr(str,token)
- register char *str,*token;
- {
- register char *ss,*tt;
-
- /* search for first char of token */
- for(ss=str; *str; str++)
- if(*str == *token)
- /* compare token with substring */
- for(ss=str,tt=token; ;)
- {
- if(*tt == 0)
- return(str);
- if(*ss++ != *tt++)
- break;
- }
- return(NULL);
- } /* end of substr */
-
- /*+-------------------------------------------------------------------------
- getfree()
-
- Routine to calculate the free bytes on the current file system ~0
- means many free bytes (unknown)
- --------------------------------------------------------------------------*/
- long
- getfree()
- {
- return(~0L); /* many free bytes ... */
- } /* end of getfree */
-
- /*+-------------------------------------------------------------------------
- usage(fail_reason)
- --------------------------------------------------------------------------*/
- void
- usage(fail_reason)
- char *fail_reason;
- {
- fprintf(stderr,"%s\n",fail_reason);
- exit(255);
- } /* end of usage */
-
- /*+-------------------------------------------------------------------------
- SIGALRM_handler()
- --------------------------------------------------------------------------*/
- void
- SIGALRM_handler()
- {
- report_tx_ind(0);
- report_rx_ind(0);
- longjmp(tohere,-1);
- } /* end of SIGALRM_handler */
-
- /*+-------------------------------------------------------------------------
- bye_bye(sig)
- --------------------------------------------------------------------------*/
- void
- bye_bye(sig)
- int sig;
- {
- exit(sig+128);
- } /* end of bye_bye */
-
- /*+-------------------------------------------------------------------------
- cancel_transaction(sig)
- called by signal interrupt or terminate to clean things up
- --------------------------------------------------------------------------*/
- void
- cancel_transaction(sig)
- {
- if(Zmodem)
- zmputs(Attn);
- send_cancel();
- mode(0);
- if(sig >= 0)
- {
- sprintf(s128,"tiprz aborted (signal %d)",sig);
- report_str(s128,0);
- }
- report_tx_ind(0);
- report_rx_ind(0);
- report_uninit(0);
- bye_bye(sig);
- } /* end of cancel_transaction */
-
- /*+-------------------------------------------------------------------------
- sendline(c) - send a character to DCE
- --------------------------------------------------------------------------*/
- sendline(c)
- char c;
- {
- write(iofd,&c,1);
- ++tx_char_count;
- } /* end of sendline */
-
- /*+-------------------------------------------------------------------------
- xsendline(c)
- --------------------------------------------------------------------------*/
- xsendline(c)
- {
- sendline(c);
- } /* end of xsendline */
-
- /*+-------------------------------------------------------------------------
- flushline()
- --------------------------------------------------------------------------*/
- flushline()
- {
- } /* end of flushline */
-
- /*+-------------------------------------------------------------------------
- purgeline() - purge the modem input queue of all characters
- --------------------------------------------------------------------------*/
- purgeline()
- {
- Lleft = 0;
- #if defined(M_XENIX) || defined(M_UNIX)
- ioctl(iofd,TCFLSH,0);
- #else
- lseek(iofd,0L,2);
- #endif
- } /* end of purgeline */
-
- /*+-------------------------------------------------------------------------
- wcreceive(argc,argp)
- --------------------------------------------------------------------------*/
- wcreceive(argc,argp)
- int argc;
- char **argp;
- {
- register c;
-
- if(Batch || argc==0)
- {
- Crcflg=1;
- c=tryz();
- if(Zmodem)
- {
- report_protocol_type("ZMODEM");
- report_protocol_crc_type((Crc32) ? "/CRC32" : "/CRC16");
- }
- if(c)
- {
- if(c == ZCOMPL)
- return(OK);
- if(c == ERROR)
- goto fubar;
- c = rzfiles();
- if(c)
- goto fubar;
- } else
- {
- report_protocol_type("YMODEM");
- report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
- for(;;)
- {
- if(wcrxpn(secbuf)== ERROR)
- goto fubar;
- if(secbuf[0]==0)
- return(OK);
- if(procheader(secbuf) == ERROR)
- goto fubar;
- report_str("Receiving data",0);
- if(wcrx()==ERROR)
- goto fubar;
- }
- }
- }
- else
- {
- report_protocol_type("XMODEM");
- report_protocol_crc_type((Crcflg) ? "/CRC" : "/CHK");
- Bytesleft = DEFBYTL;
- Filemode = 0;
- Modtime = 0L;
- procheader("");
- strcpy(Pathname,*argp);
- if((fout=fopen(Pathname,"w")) == NULL)
- {
- sprintf(s128,"%-0.85s: %-0.40s",Pathname,sys_errlist[errno]);
- report_str(s128,1);
- goto fubar;
- }
-
- report_file_rcv_started( Pathname,0L,Modtime,Filemode);
- this_file_length = 0;
- report_rxpos(0L);
- report_str("Receiving data",0);
- if(wcrx()==ERROR)
- goto fubar;
- }
- return(OK);
- fubar:
- send_cancel();
- if(fout)
- {
- fflush(fout);
- fstat(fileno(fout),&fout_stat);
- report_file_byte_io((long)fout_stat.st_size);
- report_file_close();
- fclose(fout);
- }
- return(ERROR);
- } /* end of wcreceive */
-
- /*+-------------------------------------------------------------------------
- wcgetsec(rxbuf,maxtime)
-
- Wcgetsec fetches a Ward Christensen type sector. Returns sector
- number encountered or ERROR if valid sector not received, or CAN CAN
- received or WCEOT if eot sector time is timeout for first char,set to
- 4 seconds thereafter. NO ACK IS SENT IF SECTOR IS RECEIVED OK. Caller
- must do that when he is good and ready to get next sector.
- --------------------------------------------------------------------------*/
- unsigned int
- wcgetsec(rxbuf,maxtime)
- char *rxbuf;
- int maxtime;
- {
- register unsigned int firstch;
- register unsigned short oldcrc;
- register unsigned char checksum;
- register wcj;
- register char *p;
- int sectcurr;
-
- for(Lastrx=errors=0; errors<RETRYMAX; errors++)
- {
-
- firstch=readline(maxtime);
- if((firstch == STX) || (firstch == SOH))
- {
- oldBlklen = Blklen;
- if(firstch == STX)
- Blklen=1024;
- else
- Blklen=128;
- if(oldBlklen != Blklen)
- report_rxblklen(Blklen);
-
- sectcurr=readline(1);
- if((sectcurr + (oldcrc=readline(1))) == 0xFF)
- {
- oldcrc=checksum=0;
- for(p=rxbuf,wcj=Blklen; --wcj>=0; )
- {
- if((firstch=readline(1)) < 0)
- goto bilge;
- oldcrc=updcrc(firstch,oldcrc);
- checksum += (*p++ = firstch);
- }
- if((firstch=readline(1)) < 0)
- goto bilge;
- if(Crcflg)
- {
- oldcrc=updcrc(firstch,oldcrc);
- if((firstch=readline(1)) < 0)
- goto bilge;
- oldcrc=updcrc(firstch,oldcrc);
- if(oldcrc)
- {
- sprintf(s128,"CRC error = 0x%04x",oldcrc);
- report_str(s128,1);
- }
- else
- {
- Firstsec=0;
- return(sectcurr);
- }
- }
- else if((checksum-firstch)==0)
- {
- Firstsec=0;
- return(sectcurr);
- }
- else
- report_str("checksum error",1);
- }
- else
- {
- report_last_txhdr("Noise",0);
- sprintf(s128,"Sector garbled 0x%x 0x%x",sectcurr,oldcrc);
- report_str(s128,1);
- }
- }
- /* make sure eot really is eot and not just mixmash */
- #if defined(NFGVMIN)
- else if(firstch==EOT && readline(1)==TIMEOUT)
- return(WCEOT);
- #else
- else if(firstch==EOT && Lleft==0)
- return(WCEOT);
- #endif
- else if(firstch==EOT)
- {
- report_str("Noisy EOT",2);
- }
- else if(firstch==CAN)
- {
- if(Lastrx==CAN)
- {
- report_str("Sender CANcelled",1);
- report_last_rxhdr("CAN",1);
- return(ERROR);
- } else
- {
- Lastrx=CAN;
- continue;
- }
- }
- else if(firstch==TIMEOUT)
- {
- if(Firstsec)
- goto humbug;
- bilge:
- report_str("Timeout",1);
- }
- else
- {
- sprintf(s128,"Got 0x%02x sector header",firstch);
- report_str(s128,1);
- }
-
- humbug:
- Lastrx=0;
- while(readline(1)!=TIMEOUT)
- ;
- if(Firstsec)
- {
- sendline(Crcflg?WANTCRC:NAK);
- report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
- Lleft=0; /* Do read next time ... */
- } else
- {
- maxtime=40;
- sendline(NAK);
- report_last_txhdr("NAK",1);
- Lleft=0; /* Do read next time ... */
- }
- }
- /* try to stop the bubble machine. */
- send_cancel();
- return(ERROR);
- } /* end of wcgetsec */
-
- /*+-------------------------------------------------------------------------
- wcrxpn(rpn)
-
- Fetch a pathname from the other end. Length is indeterminate as long
- as less than Blklen. During YMODEM xfers, a null string represents no
- more files.
- --------------------------------------------------------------------------*/
- wcrxpn(rpn)
- char *rpn; /* receive a pathname */
- {
- register c;
-
- #if defined(NFGVMIN)
- readline(1);
- #else
- purgeline();
- #endif
-
- et_tu:
- Firstsec=1;
- Eofseen=0;
- sendline(Crcflg?WANTCRC:NAK);
- report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
- Lleft=0; /* Do read next time ... */
- while((c = wcgetsec(rpn,100)) != 0)
- {
- if(c == WCEOT)
- {
- sprintf(s128,"Pathname fetch returned %d",c);
- report_str(s128,1);
- sendline(ACK);
- report_last_txhdr("ACK",0);
- Lleft=0; /* Do read next time ... */
- readline(1);
- goto et_tu;
- }
- return(ERROR);
- }
- sendline(ACK);
- report_last_txhdr("ACK",0);
- return(OK);
- } /* end of wcrxpn */
-
- /*+-------------------------------------------------------------------------
- write_sec_to_disk(buf,n)
-
- Putsec writes the n characters of buf to receive file fout. If not in
- binary mode, carriage returns, and all characters starting with CPMEOF
- are discarded.
- --------------------------------------------------------------------------*/
- write_sec_to_disk(buf,n)
- char *buf;
- register n;
- {
- register char *p;
-
- if(n == 0)
- return(OK);
- if(Thisbinary)
- {
- for(p=buf; --n>=0; )
- putc( *p++,fout);
- }
- else
- {
- if(Eofseen)
- return(OK);
- for(p=buf; --n>=0; ++p )
- {
- if( *p == '\r')
- continue;
- if(*p == CPMEOF)
- {
- Eofseen=1;
- fflush(fout);
- fstat(fileno(fout),&fout_stat);
- report_rxpos(fout_stat.st_size);
- return(OK);
- }
- putc(*p ,fout);
- }
- }
- fflush(fout);
- fstat(fileno(fout),&fout_stat);
- report_rxpos(fout_stat.st_size);
- if(this_file_length != 0)
- {
- sprintf(s128,"Receiving data (%u%% complete)",
- (unsigned int)(
- ((unsigned long)fout_stat.st_size * (unsigned long)100)
- / this_file_length));
- report_str(s128,0);
- }
- return(OK);
- } /* end of write_sec_to_disk */
-
- /*+-------------------------------------------------------------------------
- wcrx() - receive an X/YMODEM sector
-
- Adapted from CMODEM13.C,written by Jack M. Wierda and Roderick W. Hart
- --------------------------------------------------------------------------*/
- int
- wcrx()
- {
- register unsigned int sectnum,sectcurr;
- register unsigned char sendchar;
- register unsigned char *p;
- int cblklen; /* bytes to dump this block */
-
- Firstsec=1;
- sectnum=0;
- Eofseen=0;
- sendchar=Crcflg ? WANTCRC : NAK;
- report_last_txhdr(Crcflg ? "WANTCRC" : "NAK",0);
-
- for(;;)
- {
- sendline(sendchar); /* send it now,we're ready! */
- if(sendchar == ACK)
- report_last_txhdr("ACK",0);
- Lleft=0; /* Do read next time ... */
- sectcurr=wcgetsec(secbuf,(sectnum&0177)?50:130);
- sprintf(s128,"Block %d received",sectnum);
- report_last_rxhdr(s128,0);
- fstat(fileno(fout),&fout_stat);
- report_rxpos(fout_stat.st_size);
- if(sectcurr == (sectnum+1 & 0xFF))
- {
- sectnum++;
- cblklen = Bytesleft>Blklen ? Blklen : Bytesleft;
- if(write_sec_to_disk(secbuf,cblklen) == ERROR)
- return(ERROR);
- if((Bytesleft-=cblklen) < 0)
- Bytesleft = 0;
- sendchar=ACK;
- }
- else if(sectcurr == sectnum)
- {
- report_str("Received duplicate Sector",-1);
- sendchar = ACK;
- }
- else if(sectcurr == WCEOT)
- {
- if(close_and_report())
- return(ERROR);
- sendline(ACK);
- report_last_txhdr("ACK",0);
- Lleft=0; /* Do read next time ... */
- return(OK);
- }
- else if(sectcurr==ERROR)
- return(ERROR);
- else
- {
- report_str( "Sync Error",1);
- return(ERROR);
- }
- }
- } /* end of wcrx */
-
- /*+-------------------------------------------------------------------------
- readline(timeout)
-
- read one or more characters timeout is in tenths of seconds
- --------------------------------------------------------------------------*/
- readline(timeout)
- int timeout;
- {
- register n;
- static unsigned char *cdq; /* pointer for removing chars from linbuf */
-
- if(--Lleft >= 0)
- return(*cdq++);
-
- n = timeout/10;
- if(n < 2)
- n = 3;
- if(setjmp(tohere))
- {
- Lleft = 0;
- return(TIMEOUT);
- }
- signal(SIGALRM,SIGALRM_handler);
- alarm(n);
- Lleft = read(iofd,cdq = linbuf,Readnum);
- alarm(0);
- rx_char_count += Lleft;
-
- if(Lleft < 1)
- return(TIMEOUT);
-
- --Lleft;
- return(*cdq++);
-
- } /* end of readline */
-
- /*+-------------------------------------------------------------------------
- mkdir(dpath,dmode)
- Directory-creating routines from Public Domain TAR by John Gilmore
- Make a directory. Compatible with the mkdir() system call on 4.2BSD.
- --------------------------------------------------------------------------*/
- #if defined(MD)
- #if (MD != 2)
- #define TERM_SIGNAL(status) ((status) & 0x7F)
- #define TERM_COREDUMP(status) (((status) & 0x80) != 0)
- #define TERM_VALUE(status) ((status) >> 8)
- mkdir(dpath,dmode)
- char *dpath;
- int dmode;
- {
- int cpid,status;
- struct stat statbuf;
-
- if(stat(dpath,&statbuf) == 0)
- {
- errno = EEXIST; /* Stat worked,so it already exists */
- return(-1);
- }
-
- /* If stat fails for a reason other than non-existence,return error */
- if(errno != ENOENT)
- return(-1);
-
- switch(cpid = fork())
- {
-
- case -1: /* Error in fork() */
- return(-1); /* Errno is set already */
-
- case 0: /* Child process */
- /*
- * Cheap hack to set mode of new directory. Since this
- * child process is going away anyway,we zap its umask.
- * FIXME,this won't suffice to set SUID,SGID,etc. on this
- * directory. Does anybody care?
- */
- status = umask(0); /* Get current umask */
- status = umask(status | (0777 & ~dmode)); /* Set for mkdir */
- execl("/bin/mkdir","mkdir",dpath,(char *)0);
- _exit(-1); /* Can't exec /bin/mkdir */
-
- default: /* Parent process */
- while(cpid != wait(&status)) ; /* Wait for kid to finish */
- }
-
- if(TERM_SIGNAL(status) != 0 || TERM_VALUE(status) != 0)
- {
- errno = EIO; /* We don't know why,but */
- return(-1); /* /bin/mkdir failed */
- }
-
- return(0);
- } /* end of mkdir */
- #endif /* MD != 2 */
- #endif /* if defined(MD) */
-
- /*+-------------------------------------------------------------------------
- make_dirs(pathname)
-
- Directory-creating routines from Public Domain TAR by John Gilmore
- After a file/link/symlink/dir creation has failed, see if it's because
- some required directory was not present, and if so, create all
- required dirs.
- --------------------------------------------------------------------------*/
- #if defined(MD)
- make_dirs(pathname)
- register char *pathname;
- {
- register char *p; /* Points into path */
- int madeone = 0; /* Did we do anything yet? */
- int save_errno = errno; /* Remember caller's errno */
-
- if(errno != ENOENT)
- return(0); /* Not our problem */
-
- for(p = strchr(pathname,'/'); p != NULL; p = strchr(p+1,'/'))
- {
- /* Avoid mkdir of empty string,if leading or double '/' */
- if(p == pathname || p[-1] == '/')
- continue;
- /* Avoid mkdir where last part of path is '.' */
- if(p[-1] == '.' && (p == pathname+1 || p[-2] == '/'))
- continue;
- *p = 0; /* Truncate the path there */
- if( !mkdir(pathname,0777)) /* Try to create it as a dir */
- {
- sprintf(s128,"Made directory %s",pathname);
- report_str(s128,-1);
- madeone++; /* Remember if we made one */
- *p = '/';
- continue;
- }
- *p = '/';
- if(errno == EEXIST) /* Directory already exists */
- continue;
- /*
- * Some other error in the mkdir. We return to the caller.
- */
- break;
- }
- errno = save_errno; /* Restore caller's errno */
- return(madeone); /* Tell them to retry if we made one */
- } /* end of make_dirs */
- #endif /* MD */
-
- /*+-------------------------------------------------------------------------
- uncaps(str) - make string str lower case
- --------------------------------------------------------------------------*/
- void
- uncaps(str)
- register char *str;
- {
- register int itmp;
-
- while(itmp = *str)
- {
- if(isupper(itmp))
- *str = tolower(itmp);
- str++;
- }
- } /* end of uncaps */
-
- /*+-------------------------------------------------------------------------
- isanylc(str) - returns 1 if string str has any lower case letters
- --------------------------------------------------------------------------*/
- int
- isanylc(str)
- register char *str;
- {
- while(*str)
- {
- if(islower(*str))
- return(1);
- str++;
- }
- return(0);
- } /* end of isanylc */
-
- /*+-------------------------------------------------------------------------
- procheader(name) - process incoming file information header
- --------------------------------------------------------------------------*/
- int
- procheader(name)
- char *name;
- {
- register char *openmode,*p,**pp;
- #if defined(M_UNIX)
- char *cptr;
- char name2[PATHLEN];
- #endif
-
- /* set default parameters and overrides */
- openmode = "w";
- Thisbinary = (!Rxascii) || Rxbinary;
- if(Lzmanag)
- zmanag = Lzmanag;
-
- /*
- * Process ZMODEM remote file management requests
- */
- if(!Rxbinary && zconv == ZCNL) /* Remote ASCII override */
- Thisbinary = 0;
- if(zconv == ZCBIN) /* Remote Binary override */
- Thisbinary = 1;
- else if(zmanag == ZMAPND)
- openmode = "a";
-
- report_xfer_mode(Thisbinary ? "BINARY" : "ASCII");
- this_file_errors = 0;
-
- Bytesleft = DEFBYTL;
- Filemode = 0;
- Modtime = 0L;
- this_file_length = 0;
-
- if(strlen(name))
- p = name + 1 + strlen(name);
- else
- p = name;
-
- if(*p)
- { /* file coming from Unix or DOS system */
- int sscanf_count;
- int SerialNumber;
- int Filesleft;
- long TotalLeft;
-
- sscanf_count = sscanf(p,"%ld%lo%o%d&d&ld",
- &Bytesleft,&Modtime,&Filemode,&SerialNumber,
- &Filesleft,&TotalLeft);
-
- switch(sscanf_count)
- {
- case 6: /* TotalLeft */
- if(!TotalToReceive)
- TotalToReceive = TotalLeft;
- case 5: /* Filesleft */
- if(!npats)
- npats = Filesleft;
- default:
- break;
- }
-
- if((zmanag & ZMMASK) == ZMNEW)
- {
- if(stat(name,&fout_stat) == 0) /* if file accessable ... */
- {
- if(Modtime <= fout_stat.st_mtime) /* ... and not older */
- {
- sprintf(s128,"RECEIVE skipped: %s (same or later date)",
- name);
- report_str(s128 + 8,-1);
- skip_count++;
- report_error_count();
- return(ERROR);
- }
- }
- }
- /* Check for existing file */
- else if(!Rxclob && ((zmanag & ZMMASK) != ZMCLOB) &&
- (fout=fopen(name,"r")))
- {
- fclose(fout);
- sprintf(s128,"RECEIVE skipped: %s (already exists)",name);
- report_str(s128 + 8,-1);
- skip_count++;
- report_error_count();
- return(ERROR);
- }
-
- if(Filemode & UNIXFILE)
- ++Thisbinary;
- ++Filcnt;
-
- report_file_rcv_started( name,
- (Bytesleft != DEFBYTL) ? Bytesleft : 0,Modtime,Filemode);
- report_rxpos(0L);
- report_str("",0); /* get rid of End of File */
- if(Bytesleft != DEFBYTL)
- {
- long min_100;
- this_file_length = Bytesleft;
- min_100 = 2L + (((Bytesleft * 11L)) * 10L) / (Baudrate * 6L);
- sprintf(s128,"Receive time this file ~= %2lu:%02lu",
- min_100 / 100,((min_100 % 100) * 60L) / 100L);
- if(TotalToReceive)
- {
- min_100 = 2L +
- (((TotalToReceive * 11L)) * 10L) / (Baudrate * 6L);
- if(Baudrate > 4800)
- {
- min_100 *= 13;
- min_100 /= 9; /* yech ... empirical */
- }
- sprintf(&s128[strlen(s128)],", transaction ~= %2lu:%02lu",
- min_100 / 100,((min_100 % 100) * 60L) / 100L);
- }
- report_transaction(s128);
- sprintf(s128,"Receiving data (%d%% complete)",(int)0);
- report_str(s128,0);
- }
- }
- else
- { /* File coming from CP/M system */
- long now;
- for(p=name; *p; ++p) /* change / to _ */
- {
- if( *p == '/')
- *p = '_';
- }
-
- if( *--p == '.') /* zap trailing period */
- *p = 0;
- time(&now);
- report_file_rcv_started( name,
- (Bytesleft != DEFBYTL) ? Bytesleft : 0,now,0);
- }
-
- if(!Zmodem && MakeLCPathname && !isanylc(name) && !(Filemode&UNIXFILE))
- uncaps(name);
-
- strcpy(Pathname,name);
- report_xfer_mode(Thisbinary?"BINARY":"ASCII");
- fout = fopen(name,openmode);
- #if defined(MD)
- if( !fout)
- if(make_dirs(name))
- fout = fopen(name,openmode);
- #endif
- if( !fout)
- return(ERROR);
- this_file_errors = 0;
- return(OK);
- } /* end of procheader */
-
- /*+-------------------------------------------------------------------------
- send_cancel() - send cancel string
- --------------------------------------------------------------------------*/
- send_cancel()
- {
- static char canistr[] =
- {
- 24,24,24,24,24,24,24,24,24,24,8,8,8,8,8,8,8,8,8,8,0
- };
- register char *cptr = canistr;
-
- report_str("",0);
- report_last_txhdr("^X CAN",1);
- while(*cptr)
- sendline(*cptr++);
- Lleft=0;
- } /* end of send_cancel */
-
- /*+-------------------------------------------------------------------------
- tryz()
-
- Initialize for Zmodem receive attempt, try to activate Zmodem sender
- Handles ZSINIT frame
- Return ZFILE if Zmodem filename received,-1 on error,
- ZCOMPL if transaction finished, else 0
- --------------------------------------------------------------------------*/
- int
- tryz()
- {
- register c,n;
-
- if(Nozmodem) /* Check for "rb" program name */
- return(0);
-
- for(n=Zmodem?15:5; --n>=0; )
- {
- /* Set buffer length (0) and capability flags */
- stohdr(0L);
- #if defined(CANBREAK)
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO|CANBRK;
- #else
- Txhdr[ZF0] = CANFC32|CANFDX|CANOVIO;
- #endif
- if(Zctlesc)
- Txhdr[ZF0] |= TESCCTL;
- zshhdr(tryzhdrtype,Txhdr);
- if(tryzhdrtype == ZSKIP) /* Don't skip too far */
- tryzhdrtype = ZRINIT; /* CAF 8-21-87 */
- again:
- switch(zgethdr(Rxhdr,0))
- {
- case ZRQINIT:
- continue;
- case ZEOF:
- continue;
- case TIMEOUT:
- continue;
- case ZFILE:
- zconv = Rxhdr[ZF0];
- zmanag = Rxhdr[ZF1];
- ztrans = Rxhdr[ZF2];
-
- strcpy(s128,"Transfer: ");
- switch(zmanag & ZMMASK)
- {
- case 0:
- strcat(s128,"if destination nonexistent");
- break;
- case ZMAPND: /* Append contents to existing file (if any) */
- strcat(s128,"append to destination");
- break;
- case ZMCLOB: /* Replace existing file */
- strcat(s128,"absolute (overwrite)");
- break;
- case ZMNEW:
- strcat(s128,"if source newer");
- break;
- default:
- sprintf(s128 + strlen(s128),
- "absolute (%02x)",zmanag & ZMMASK);
- break;
- }
- report_str(s128,2);
-
- tryzhdrtype = ZRINIT;
- c = zrdata(secbuf,1024);
- mode(3);
- if(c == GOTCRCW)
- return(ZFILE);
- zshhdr(ZNAK,Txhdr);
- goto again;
- case ZSINIT:
- Zctlesc = TESCCTL & Rxhdr[ZF0];
- if(zrdata(Attn,ZATTNLEN) == GOTCRCW)
- {
- stohdr(1L);
- zshhdr(ZACK,Txhdr);
- report_str("",-1);
- goto again;
- }
- zshhdr(ZNAK,Txhdr);
- goto again;
- case ZFREECNT:
- stohdr(getfree());
- zshhdr(ZACK,Txhdr);
- report_str("",-1);
- goto again;
- case ZCOMMAND:
- if(zrdata(secbuf,1024) == GOTCRCW)
- {
- stohdr(-1L);
- purgeline(); /* dump impatient questions */
- while(errors < 20)
- {
- zshhdr(ZCOMPL,Txhdr);
- if(zgethdr(Rxhdr,1) == ZFIN)
- break;
- }
- send_ZFIN_and_exit();
- return(ZCOMPL);
- }
- zshhdr(ZNAK,Txhdr);
- goto again;
- case ZCOMPL:
- goto again;
- default:
- continue;
- case ZFIN:
- send_ZFIN_and_exit();
- return(ZCOMPL);
- case ZCAN:
- return(ERROR);
- }
- }
- return(0);
- } /* end of tryz */
-
- /*+-------------------------------------------------------------------------
- rzfile() - receive a file with ZMODEM protocol
-
- assumes file name frame is in secbuf
- --------------------------------------------------------------------------*/
- rzfile()
- {
- register c,n;
- long rxbytes;
-
- Eofseen=0;
- if(procheader(secbuf) == ERROR)
- {
- return(tryzhdrtype = ZSKIP);
- }
-
- n = 20;
- rxbytes = 0l;
-
- for(;;)
- {
- stohdr(rxbytes);
- zshhdr(ZRPOS,Txhdr);
- if(rxbytes)
- report_str("Sending ZRPOS",1);
- nxthdr:
- switch(c = zgethdr(Rxhdr,0))
- {
- default:
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- case ZNAK:
- case TIMEOUT:
- if( --n < 0)
- {
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- }
- case ZFILE:
- zrdata(secbuf,1024);
- continue;
- case ZEOF:
- if(rclhdr(Rxhdr) != rxbytes)
- {
- /*
- * Ignore eof if it's at wrong place - force
- * a timeout because the eof might have gone
- * out before we sent our zrpos.
- */
- errors = 0;
- goto nxthdr;
- }
- if(close_and_report())
- {
- tryzhdrtype = ZFERR;
- return(ERROR);
- }
- report_str("End of file",0);
- return(c);
- case ERROR: /* Too much garbage in header search error */
- if( --n < 0)
- {
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- }
- zmputs(Attn);
- continue;
- case ZSKIP:
- close_and_report();
- sprintf(s128,"rzfile: Sender SKIPPED file");
- report_str(s128,1);
- return(c);
- case ZDATA:
- if(rclhdr(Rxhdr) != rxbytes)
- {
- if( --n < 0)
- {
- return(ERROR);
- }
- zmputs(Attn);
- continue;
- }
- moredata:
- switch(c = zrdata(secbuf,1024))
- {
- case ZCAN:
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- case ERROR: /* CRC error */
- if( --n < 0)
- {
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- }
- zmputs(Attn);
- continue;
- case TIMEOUT:
- if( --n < 0)
- {
- sprintf(s128,"zgethdr returned %02x",c);
- report_str(s128,1);
- return(ERROR);
- }
- continue;
- case GOTCRCW:
- n = 20;
- write_sec_to_disk(secbuf,Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(ZACK,Txhdr);
- report_str("",-1);
- sendline(XON);
- goto nxthdr;
- case GOTCRCQ:
- n = 20;
- write_sec_to_disk(secbuf,Rxcount);
- rxbytes += Rxcount;
- stohdr(rxbytes);
- zshhdr(ZACK,Txhdr);
- report_str("",-1);
- goto moredata;
- case GOTCRCG:
- n = 20;
- write_sec_to_disk(secbuf,Rxcount);
- rxbytes += Rxcount;
- goto moredata;
- case GOTCRCE:
- n = 20;
- write_sec_to_disk(secbuf,Rxcount);
- rxbytes += Rxcount;
- goto nxthdr;
- }
- }
- }
- } /* end of rzfile */
-
- /*+-------------------------------------------------------------------------
- rzfiles() - receive file(s) with ZMODEM protocol
- --------------------------------------------------------------------------*/
- rzfiles()
- {
- register c;
-
- for(;;)
- {
- switch(c = rzfile())
- {
- case ZEOF:
- case ZSKIP:
- switch(tryz())
- {
- case ZCOMPL:
- return(OK);
- default:
- return(ERROR);
- case ZFILE:
- break;
- }
- continue;
- default:
- return(c);
- case ERROR:
- return(ERROR);
- }
- }
- } /* end of rzfiles */
-
- /*+-------------------------------------------------------------------------
- close_and_report() - close the received file, set mod time and chmod
- (specifically exclude set uid and gid from chmod)
- --------------------------------------------------------------------------*/
- close_and_report()
- {
- fflush(fout);
- fstat(fileno(fout),&fout_stat);
- report_file_byte_io((long)fout_stat.st_size);
- report_file_close();
-
- if(fclose(fout)==ERROR)
- return(ERROR);
-
- if(Modtime)
- {
- timep[0] = time(NULL);
- timep[1] = Modtime;
- utime(Pathname,timep);
- }
-
- if((Filemode & S_IFMT) == S_IFREG)
- {
- Filemode &= ~(S_ISUID | S_ISGID);
- chmod(Pathname,(07777 & Filemode));
- }
-
- return(OK);
-
- } /* end of close_and_report */
-
- /*+-------------------------------------------------------------------------
- send_ZFIN_and_exit() - send ZFIN packet and wait for "OO" ack
- --------------------------------------------------------------------------*/
- send_ZFIN_and_exit()
- {
- register n;
-
- Readnum = 1;
- stohdr(0L);
- for(n = 0; n < 4; n++)
- {
- purgeline();
- zshhdr(ZFIN,Txhdr);
- switch(readline(100))
- {
- case 'O':
- readline(1); /* Discard 2nd 'O' */
- return;
- case RCDO:
- return;
- case TIMEOUT:
- default:
- break;
- }
- }
- } /* end of send_ZFIN_and_exit */
-
- /*+-------------------------------------------------------------------------
- sys2(shellcmd) - extipte shell command
-
- Strip leading ! if present
- --------------------------------------------------------------------------*/
- sys2(shellcmd)
- register char *shellcmd;
- {
- if(*shellcmd == '!')
- ++shellcmd;
- return(system(shellcmd));
- } /* end of sys2 */
-
- /*+-------------------------------------------------------------------------
- main(argc,argv,envp)
- --------------------------------------------------------------------------*/
- main(argc,argv,envp)
- int argc;
- char **argv;
- char **envp;
- {
- register char *cp;
- char **patts;
- char *getenv();
- int exitcode = 0;
- char **gargv = argv;
- int gargc = argc;
-
- signal(SIGINT,bye_bye);
- signal(SIGTERM,bye_bye);
-
- get_curr_dir(curr_dir,sizeof(curr_dir));
-
- Rxtimeout = 100;
-
- npats = 0;
- while(--argc)
- {
- cp = *++argv;
- if(*cp == '-')
- {
- while( *++cp)
- {
- switch(*cp)
- {
- case 'X':
- required_type = 1;
- Batch = 0;
- break;
- case 'Y':
- required_type = 1;
- Nozmodem = 1;
- Batch = 1;
- break;
- case 'Z':
- required_type = 1;
- Nozmodem = 0;
- Batch = 1;
- break;
- case '+':
- Lzmanag = ZMAPND;
- break;
- case 'a':
- Rxascii=1;
- break;
- case 'b':
- Rxbinary=1;
- break;
- case 'c':
- Crcflg=1;
- break;
- case 'e':
- Zctlesc = 1;
- break;
- case 'p':
- Lzmanag = ZMPROT;
- break;
- case ',':
- log_packets = 1;
- break;
- case '.':
- if(--argc < 1)
- {
- usage("no iofd after -.");
- }
- iofd = atoi(*++argv);
- break;
- case 't':
- if(--argc < 1)
- {
- usage("no rcvr timeout after -t");
- }
- Rxtimeout = atoi(*++argv);
- if(Rxtimeout<10 || Rxtimeout>1000)
- usage("illegal timeout: must be 10 <= t <= 1000");
- break;
- case 'w':
- if(--argc < 1)
- {
- usage("no Zrwindow after -w");
- }
- Zrwindow = atoi(*++argv);
- break;
- case 'C':
- if(--argc < 1)
- usage("no label after -C");
- bottom_label = *++argv;
- break;
- case 'u':
- MakeLCPathname=0;
- break;
- case 'y':
- Rxclob=1;
- break;
- default:
- sprintf(s128,"Unknown switch -%c",*cp);
- usage(s128);
- }
- }
- }
- else if( !npats && argc>0)
- {
- if(argv[0][0])
- {
- npats=argc;
- patts=argv;
- }
- }
- }
-
- if(!required_type || !iofd)
- {
- printf("can only be run by tip\n");
- exit(255);
- }
-
- if(log_packets)
- {
- char log_packets_name[64];
- FILE *ftmp;
- int iargv;
- sprintf(log_packets_name,"/tmp/rz%05d.plog",getpid());
- unlink(log_packets_name);
- ftmp = fopen(log_packets_name,"w");
- fclose(ftmp);
- log_packets = open(log_packets_name,O_WRONLY,0644);
- if(log_packets < 0)
- log_packets = 0;
- else
- {
- write(log_packets,"exec: ",6);
- for(iargv = 0; iargv < gargc; iargv++)
- {
- write(log_packets,gargv[iargv],strlen(gargv[iargv]));
- write(log_packets," ",1);
- }
- write(log_packets,"\n",1);
- }
- }
-
-
- if(Batch && npats)
- usage("Cannot specify batch receive and filename");
- if(npats > 1)
- usage("only one filename allowed");
- sprintf(s128,"%s",numeric_revision);
- report_init(s128);
- mode(1);
- signal(SIGINT,cancel_transaction);
- signal(SIGTERM,cancel_transaction);
- signal(SIGQUIT,cancel_transaction);
- if(wcreceive(npats,patts)==ERROR)
- {
- exitcode=0200;
- send_cancel();
- }
- mode(0);
- if(exitcode && !Zmodem) /* bellow again with all thy might. */
- send_cancel();
- report_uninit(0);
- exit(exitcode);
- }
-
- /* vi: set tabstop=4 shiftwidth=4: */
- /* end of tiprz.c */
-